/*****************************************************************************
* Author:		Wesley Maxey
* Filename:		SuperString.h
* Date Created:	4/10/2013
*
* Overview:
*	String class that creates an extremely simple interface for building
*	strings out of different native types (int, char *, bool, etc... )
*
* Member Functions:
*public:
*	SuperString()
*	SuperString( const Tx ... )
*	void setString( const Tx ... )
*	char * getString()
*	~SuperString()
*private:
*	void unwindArgs( const T, const Tx ... )
*	void unwindArgs()
*	void extractType() //Heavily overloaded function for deducing base type
*
* Contained Data:
*private:
*	char * m_str
*	int m_len
*
*****************************************************************************/

#include <iostream>

class SuperString {
public:
	SuperString() : m_str(nullptr), m_len(0) { }

	template <typename ... Tx>
	SuperString( const Tx &... );

	const char const * getString() {return m_str;}
	template <typename ... Tx>
	void setString( const Tx &... );

	~SuperString() { delete [] m_str; }
private:
	template <typename T, typename ... Tx>
	void unwindArgs( const T &, const Tx &... );
	inline void unwindArgs() {}

	inline void extractType( const int & arg ) {
		char buffer[8];
		int m_len_off;
		itoa( arg, buffer, 10 );
		m_len_off = strlen( buffer );
		strcpy( m_str + m_len, buffer );
		m_len += m_len_off;
	}
	inline void extractType( const char * arg) {
		int m_len_off( strlen( arg ) );
		strcpy( m_str + m_len, arg );
		m_len += m_len_off;
	}
	inline void extractType( const char & arg) {
		m_str[m_len] = arg;
		m_len++;
	}
	inline void extractType( const float & arg) {
		char buffer[8];
		int m_len_off;
		sprintf( buffer, "%f", arg );
		m_len_off = strlen( buffer );
		strcpy( m_str + m_len, buffer );
		m_len += m_len_off;
	}
	inline void extractType( const short & arg)	{
		char buffer[8];
		int m_len_off;
		itoa( arg, buffer, 10 );
		m_len_off = strlen( buffer );
		strcpy( m_str + m_len, buffer );
		m_len += m_len_off;
	}
	inline void extractType( const bool & arg) {
		char buffer[8];
		int m_len_off;
		itoa( arg, buffer, 10 );
		m_len_off = strlen( buffer );
		strcpy( m_str + m_len, buffer );
		m_len += m_len_off;
	}
	inline void extractType( const long & arg) {
		char buffer[32];
		int m_len_off;
		ltoa( arg, buffer, 10 );
		m_len_off = strlen( buffer );
		strcpy( m_str + m_len, buffer );
		m_len += m_len_off;
	}
	inline void extractType( const double & arg) {
		char buffer[8];
		int m_len_off;
		sprintf( buffer, "%f", arg );
		m_len_off = strlen( buffer );
		strcpy( m_str + m_len, buffer );
		m_len += m_len_off;
	}

	char * m_str;
	int m_len;
};

//Constructor that creates the superstring
template <typename ... Tx>
SuperString::SuperString( const Tx &... argx ) : m_str(nullptr), m_len(0)
{
	m_str = new char[256];

	unwindArgs( argx... );
}

//Recreates the superstring with new data
template <typename ... Tx>
void SuperString::setString( const Tx &... argx ) 
{
	delete [] m_str;
	m_len = 0;
	m_str = new char[256];

	unwindArgs( argx... );
}

//Unwinds arguments passed in via varaidic templating
template <typename T, typename ... Tx>
void SuperString::unwindArgs( const T & arg, const Tx &... argx )
{
	extractType( arg );
	unwindArgs( argx... );
}